package edu.uwm.universitydb.controller;

import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;

import javax.swing.JOptionPane;

import edu.uwm.universitydb.authenticaion.AuthenticationHelper;
import edu.uwm.universitydb.framework.exception.DataAccessErrorCode;
import edu.uwm.universitydb.framework.exception.DataAccessException;
import edu.uwm.universitydb.model.Role;
import edu.uwm.universitydb.model.User;
import edu.uwm.universitydb.service.ServiceFactory;
import edu.uwm.universitydb.service.login.LoginService;
import edu.uwm.universitydb.view.Login;
import edu.uwm.universitydb.view.Main;

public class MainController implements MouseListener, KeyListener {

	public static void main(String[] args) {
		//We startup our main controller
		MainController mainController = new MainController();
		mainController.begin();
	}
	
	public void begin() {
		//Create our Frame
		_frame = new Main();
		_frame.build();
		
		//Initialize our login app
		_login = new LoginController();
		_frame.addCard(_login.getView(), LoginController.ID);
	
		//Add the initial listeners
		_frame.getLogoutLink().addMouseListener(this);
		_login.getSignInButton().addMouseListener(this);
		_login.getPasswordField().addKeyListener(this);
		_frame.show();
	}
	
	private void onLogoutClick() {
		//First let's clear the menu items
		_frame.clearMenuItems();
		//Navigate back to Login
		_login.getView().resetFields();
		_frame.setCard(LoginController.ID);
	}
	
	private void onSignInClick() {
		
		final ServiceFactory serviceFactory = ServiceFactory.getInstance();
		final String databseUrl = _login.getView().getDbUrl();
		final String username = _login.getView().getUsername();
		final String password = _login.getView().getPassword();
		
				// set values to auth helper
		AuthenticationHelper.setDbUrl(databseUrl);
		AuthenticationHelper.setUserName(username);
		AuthenticationHelper.setPassword(password);
		
		// initiate the service call
		final LoginService loginService = serviceFactory.getLoginService();
		User user = null;
		try {
			user = loginService.login(username, password);
		} catch (DataAccessException e) {

			final DataAccessErrorCode code = e.getErrorCode();
			String errorMessage;
			if(code == DataAccessErrorCode.INAVLID_LOGIN || e.getMessage().startsWith("Access denied") ) {
				errorMessage = "Invalid user/password";
			}
			else {
				errorMessage = String.format("Error: %s\n%s\n%s", e.getErrorCode(), e.getMessage(), e.getStackTrace());
			}
			JOptionPane.showMessageDialog(_frame.getFrame(), errorMessage);
			return;
		}
		
		_frame.buildMenuItems(user.getRole());
		
		// Roles for all users
		StudentMaintController studentMaint = new StudentMaintController();
		_frame.addCard(studentMaint.getView(), StudentMaintController.ID);
		_frame.getStudentsMenu().addMouseListener(this);
		
		ProjectMaintController projectMaint = new ProjectMaintController(user);
		_frame.addCard(projectMaint.getView(), ProjectMaintController.ID);
		_frame.getProjectsMenu().addMouseListener(this);
		
		if (user.getRole() == Role.ADMINISTRATOR) {
		// Roles for admin users
			ProfessorMaintController proftMaint = new ProfessorMaintController();
			UserMaintController userMaint = new UserMaintController();
			DepartmentMaintController deptMaint = new DepartmentMaintController();
			PerformanceMaintController perfMaint = new PerformanceMaintController(_frame);

			_frame.addCard(proftMaint.getView(), ProfessorMaintController.ID);
			_frame.addCard(userMaint.getView(), UserMaintController.ID);
			_frame.addCard(deptMaint.getView(), DepartmentMaintController.ID);
			_frame.addCard(perfMaint.getView(), PerformanceMaintController.ID);
			_frame.getProfessorsMenu().addMouseListener(this);
			_frame.getUsersMenu().addMouseListener(this);
			_frame.getDepartmentMenu().addMouseListener(this);
			_frame.getPerformanceMenu().addMouseListener(this);
		}
		
		// Nav to first available app
		_frame.setCard(StudentMaintController.ID);
	}
	
	private void onStudentsMenuClick() {
		//Navigate to User Maintenance
		_frame.setCard(StudentMaintController.ID);
	}
	
	private void onProfessorsMenuClick() {
		//Navigate to Professor Maintenance
		_frame.setCard(ProfessorMaintController.ID);
	}
	
	private void onUsersMenuClick() {
		//Navigate to Professor Maintenance
		_frame.setCard(UserMaintController.ID);
	}
	
	private void onProjectsMenuClick() {
		//Navigate to Project Maintenance
		_frame.setCard(ProjectMaintController.ID);
	}
	
	private void onDepartmentMenuClick() {
		//Navigate to Department Maintenance
		_frame.setCard(DepartmentMaintController.ID);
	}
	
	private void onPerformanceMenuClick() {
		//Navigate to Performance Maintenance
		_frame.setCard(PerformanceMaintController.ID);
	}

	@Override
	public void mouseClicked(MouseEvent e) {
		//Based on the element clicked, fire off appropriate handler method.
		switch(e.getComponent().getName()) {
			case Main.LOGOUT: 
				this.onLogoutClick();
				break;
			case Login.SIGNINBUTTON:
				this.onSignInClick();
				break;
			case Main.STUDENTSMENU:
				this.onStudentsMenuClick();;
				break;
			case Main.PROFESSORSMENU:
				this.onProfessorsMenuClick();;
				break;
			case Main.USERSMENU:
				this.onUsersMenuClick();;
				break;
			case Main.PROJECTMENU:
				this.onProjectsMenuClick();
				break;
			case Main.DEPARTMENTMENU:
				this.onDepartmentMenuClick();;
				break;
			case Main.PERFORMANCEMENU:
				this.onPerformanceMenuClick();
				break;
			default: 
				//Not sure what they clicked, do nothing
				break;
		}
	}

	@Override
	public void mouseEntered(MouseEvent e) {
		//Unused
	}

	@Override
	public void mouseExited(MouseEvent e) {
		//Unused
	}

	@Override
	public void mousePressed(MouseEvent e) {
		//Unused
	}

	@Override
	public void mouseReleased(MouseEvent e) {
		//Unused
	}
	
	@Override
	public void keyPressed(KeyEvent arg0) {
		// Unused
		
	}

	@Override
	public void keyReleased(KeyEvent evt) {
		if(evt.getKeyCode() == KeyEvent.VK_ENTER) 
	      {
			this.onSignInClick();
	      }
		
	}

	@Override
	public void keyTyped(KeyEvent arg0) {
		// Unused
		
	}
	
	private Main _frame;
	private LoginController _login;

}
